package com.xbongbong.paas.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.business.rule.FormDataActiveRuleHelp;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.data.service.CabinetFileService;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.PaasProcessDataEntity;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.FlowStatusEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.help.FormDataValidateDataHelp;
import com.xbongbong.paas.help.FormDataValidateProductHelp;
import com.xbongbong.paas.help.ProSaveHelp;
import com.xbongbong.paas.help.UserHelp;
import com.xbongbong.paas.log.MongoLogHelp;
import com.xbongbong.paas.log.constant.LogMemoConstant;
import com.xbongbong.paas.log.thread.LogThreadPoolBeanConfig;
import com.xbongbong.paas.lowcode.LowCodeExecuteHelp;
import com.xbongbong.paas.pojo.dto.ActiveRuleDTO;
import com.xbongbong.paas.pojo.dto.FormDataUpdateDTO;
import com.xbongbong.paas.pojo.dto.SaasFormSaveDTO;
import com.xbongbong.paas.pojo.dto.StartProcessDTO;
import com.xbongbong.paas.pojo.dto.ValidateDataDTO;
import com.xbongbong.paas.pojo.vo.FormDataUpdateVO;
import com.xbongbong.paas.pojo.vo.StartProcessVO;
import com.xbongbong.paas.service.ProModelService;
import com.xbongbong.paas.service.team.TeamDataHelp;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.paas.util.FormDataUtil;
import com.xbongbong.pro.domain.entity.ReRollBackEntity;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.formdata.pojo.SaasNeedRedundantAttrPojo;
import com.xbongbong.pro.formdata.pojo.vo.BeforeUpdateVO;
import com.xbongbong.pro.formdata.pojo.vo.UpdateVO;
import com.xbongbong.pro.log.pojo.DetailLogPojo;
import com.xbongbong.pro.service.toolbox.elasticsearch.help.ProEsHelper;
import com.xbongbong.process.operate.ProcessStartHelp;
import com.xbongbong.rollback.factory.FormDataUpdateRollBackFactory;
import com.xbongbong.rollback.service.AbstractFormDataUpdateRollBackService;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.WorkOrderEntity;
import com.xbongbong.saas.domain.entity.WorkOrderExplainEntity;
import com.xbongbong.saas.domain.entity.WorkOrderFlowUserEntity;
import com.xbongbong.saas.domain.entity.WorkOrderFormEntity;
import com.xbongbong.saas.domain.entity.WorkOrderProductEntity;
import com.xbongbong.saas.domain.entity.ext.WorkOrderFormEntityExt;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.RedundantTemplateTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.WorkOrderEnum;
import com.xbongbong.saas.help.SaasSaveHelp;
import com.xbongbong.saas.model.PaasFormSubDataModel;
import com.xbongbong.saas.model.WorkOrderExplainModel;
import com.xbongbong.saas.model.WorkOrderFlowUserModel;
import com.xbongbong.saas.model.WorkOrderFormModel;
import com.xbongbong.saas.model.WorkOrderModel;
import com.xbongbong.saas.model.WorkOrderProductModel;
import com.xbongbong.saas.service.UserTeamService;
import com.xbongbong.saas.service.WorkOrderProductService;
import com.xbongbong.saas.service.WorkOrderService;
import com.xbongbong.saas.service.toolbox.help.LogHelp;
import com.xbongbong.workflow.domain.entity.WorkflowBackupDataEntity;
import com.xbongbong.workflow.model.WorkflowBackupDataModel;
import com.xbongbong.workorder.abstracts.AbstractWorkOrderUpdateDataService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

/**
 * @author 吴峰
 * @date 2021/02/23 16:03
 */
@Service("workOrderDataFormDataUpdateServiceImpl")
public class WorkOrderDataFormDataUpdateServiceImpl extends AbstractWorkOrderUpdateDataService {

    private static final Logger LOG = LoggerFactory.getLogger(WorkOrderDataFormDataUpdateServiceImpl.class);

    @Resource
    private UserHelp userHelp;
    @Resource
    private ProModelService proModelService;
    @Resource
    private WorkOrderExplainModel workOrderExplainModel;
    @Resource
    private WorkOrderFormModel workOrderFormModel;
    @Resource
    private FormDataValidateDataHelp formDataValidateDataHelp;
    @Resource
    private SaasSaveHelp saasSaveHelp;
    @Resource
    private ProcessStartHelp processStartHelp;
    @Resource
    private FormDataValidateProductHelp formDataValidateProductHelp;
    @Resource
    private WorkOrderService workOrderService;
    @Resource
    private WorkOrderModel workOrderModel;
    @Resource
    private WorkOrderProductService workOrderProductService;
    @Resource
    private CabinetFileService cabinetFileService;
    @Resource
    private UserTeamService userTeamService;
    @Resource
    private LogHelp logHelp;
    @Resource
    private MongoLogHelp mongoLogHelp;
    @Resource
    private LogThreadPoolBeanConfig logThreadPoolBeanConfig;
    @Resource
    private ProEsHelper proEsHelper;
    @Resource
    private PaasFormSubDataModel paasFormSubDataModel;
    @Resource
    private FormDataActiveRuleHelp formDataActiveRuleHelp;
    @Resource
    private WorkOrderProductModel workOrderProductModel;
    @Resource
    private WorkflowBackupDataModel workflowBackupDataModel;
    @Resource
    private WorkOrderFlowUserModel workOrderFlowUserModel;
    @Resource
    private LowCodeExecuteHelp lowCodeExecuteHelp;

    @Resource
    private TeamDataHelp teamDataHelp;

    @Override
    public List<Integer> businessType() {
        return Arrays.asList(XbbRefTypeEnum.WORK_ORDER.getCode());
    }

    @Override
    public void businessImportSetData(FieldAttrEntity fieldAttrEntity, JSONObject oldData, JSONObject newData) {

    }

    @Override
    public void afterSaveLog(FormDataUpdateDTO formDataUpdateDTO, WorkOrderFormEntityExt workOrderFormEntityExt, WorkOrderEntity workOrderEntity, WorkOrderEntity oldWorkOrderEntity, UpdateVO updateVO, BeforeUpdateVO beforeUpdateVO) throws XbbException {
        String corpid = formDataUpdateDTO.getCorpid();
        String userName = updateVO.getUserVO().getName();
        String memoName = RedundantTemplateTypeEnum.WORKORDER.getName();
        String opObjectName = workOrderEntity.getSerialNo();
        // 记录日志
        Runnable runnable = () -> {
            try {
                String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_WORK), userName, memoName, opObjectName);
                JSONObject oldObj = JSONObject.parseObject(JSONObject.toJSONString(oldWorkOrderEntity));
                JSONObject newObj = JSONObject.parseObject(JSONObject.toJSONString(workOrderEntity));
                List<DetailLogPojo> detailArr = logHelp.getDetailArr4Data(corpid, RedundantTemplateTypeEnum.WORKORDER, beforeUpdateVO.getExplainMap(), oldObj, newObj);
                mongoLogHelp.buildLog4DetailArr(detailArr, corpid, formDataUpdateDTO.getUserId(), userName, OperateModuleTypeEnum.WORK,
                        OperateTypeEnum.EDIT, formDataUpdateDTO.getDataId().toString(), opObjectName, memo, formDataUpdateDTO.getHttpHeader());
            } catch (Exception e) {
                LOG.error("com.xbongbong.paas.service.impl.workOrderFormDataUpdateServiceImpl.afterSaveLog fail", e);
            }
        };
        logThreadPoolBeanConfig.sysLogThreadPool().execute(runnable);

    }
    @Override
    public BeforeUpdateVO beforeSave(FormDataUpdateDTO formDataUpdateDTO) throws XbbException {
        try {
            String corpid = formDataUpdateDTO.getCorpid();
            WorkOrderEntity oldWorkOrderEntity = proModelService.getOldWorkOrderEntity(formDataUpdateDTO);
            WorkOrderExplainEntity workOrderExplainEntity = workOrderExplainModel.getByFormId(formDataUpdateDTO.getFormId(), oldWorkOrderEntity.getCorpid());
            Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(workOrderExplainEntity.getExplains(), null);
            WorkOrderEntity workOrderEntity = new WorkOrderEntity();
            // 这行copy不能少，少了会出问题
            BeanUtil.copyProperties(oldWorkOrderEntity, workOrderEntity);
            workOrderEntity.setSerialNo(formDataUpdateDTO.getSerialNo());
            workOrderEntity.setData(formDataUpdateDTO.getDataList());
            workOrderEntity.setId(formDataUpdateDTO.getDataId());
            // 所属部门的id，由前端传入
            WorkOrderFormEntityExt workOrderFormEntityExt = workOrderFormModel.getByKey(formDataUpdateDTO.getFormId(), corpid);
            if (workOrderFormEntityExt == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_DATA_NOT_EXIST);
            }
            String explainList1 = workOrderExplainEntity.getExplains();
            List<FieldAttrEntity> fieldList = JSONArray.parseArray(explainList1, FieldAttrEntity.class);
            ValidateDataDTO validateDataDTO = new ValidateDataDTO();
            BeanUtil.copyProperties(formDataUpdateDTO, validateDataDTO);
            //这里BeanCopy没有拷贝ownids,这里formDataUpdateDTO的ownerid要映射到validateDataDTO的ownerids里, 后面也是从validateDataDTO的ownerids里拿
            Optional.of(formDataUpdateDTO)
                    .map(FormDataUpdateDTO::getOwnerId)
                    .filter(t -> CollectionsUtil.isEmpty(validateDataDTO.getOwnerIds()))
                    .ifPresent(validateDataDTO::setOwnerIds);

            JSONObject dataObj = formDataUpdateDTO.getDataList();
            validateDataDTO.setData(dataObj);
            validateDataDTO.setExplainMap(explainMap);
            validateDataDTO.setDataId(formDataUpdateDTO.getDataId());

            // TODO: 2020/3/7 临时处理
            explainMap = ExplainUtil.getExplainMap(workOrderExplainEntity.getExplains(), null);
            validateDataDTO.setExplainMap(explainMap);

            ProSaveHelp.analyticalData(validateDataDTO);
            //基本参数校验
            formDataValidateDataHelp.validateData(validateDataDTO);
            validateDataDTO.setCreatorId(oldWorkOrderEntity.getCreatorId());
            //工单参数校验
            saasSaveHelp.beforeSave(validateDataDTO);
            formDataUpdateDTO.setSaasNeedRedundantAttrPoJo(validateDataDTO.getSaasNeedRedundantAttrPoJo());
            
            //是否启用新工作流
            if (isEnableNewWorkflow(formDataUpdateDTO, explainMap, workOrderEntity, oldWorkOrderEntity)) {
                if (!formDataUpdateDTO.getIsSatisfyTrigger()) {
                    // 无需走工作流
                    workOrderEntity.setFlowStatus(null);
                }
                BeforeUpdateVO beforeUpdateVO = new BeforeUpdateVO(explainMap, fieldList, validateDataDTO.getSaasNeedRedundantAttrPoJo(), 1, workOrderEntity, oldWorkOrderEntity, workOrderFormEntityExt);
                Long backupDataId = backupData(formDataUpdateDTO, beforeUpdateVO, workOrderFormEntityExt, workOrderEntity, oldWorkOrderEntity);
                beforeUpdateVO.setBackupDataId(backupDataId);
                return beforeUpdateVO;
            }
            
            // 进入审批
            Integer noApprovalRequired = startProcess(formDataUpdateDTO, workOrderEntity, oldWorkOrderEntity, workOrderFormEntityExt, validateDataDTO.getSaasNeedRedundantAttrPoJo());
            workOrderEntity.setData(formDataUpdateDTO.getDataList());
            workOrderEntity.setMenuId(workOrderFormEntityExt.getMenuId());
            workOrderEntity.setFormId(workOrderFormEntityExt.getId());
            // 所属部门的id，由前端传入
            workOrderEntity.setDepartmentId(validateDataDTO.getDepartmentId());
            workOrderEntity.setSerialNo(formDataUpdateDTO.getSerialNo());
            workOrderEntity.setCorpid(corpid);
            return new BeforeUpdateVO(explainMap, fieldList, validateDataDTO.getSaasNeedRedundantAttrPoJo(), noApprovalRequired, workOrderEntity, oldWorkOrderEntity, workOrderFormEntityExt);
        } catch (XbbException e) {
          throw e;
        } catch (Exception e) {
            LOG.error("workOrderFormDataUpdateServiceImpl.update 出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    
    @Override
    public UpdateVO update(FormDataUpdateDTO formDataUpdateDTO, BeforeUpdateVO beforeUpdateVO, WorkOrderFormEntityExt workOrderFormEntity, WorkOrderEntity workOrderEntity, WorkOrderEntity oldWorkOrderEntity) throws XbbException {
        UpdateVO updateVO = new UpdateVO();
        try {
            String corpid = formDataUpdateDTO.getCorpid();
            UserVO userVO = userHelp.getUserName(formDataUpdateDTO.getCorpid(), formDataUpdateDTO.getUserId(), formDataUpdateDTO.getLoginUserName(), beforeUpdateVO.getOldWorkOrderEntity().getFlowStatus(), beforeUpdateVO.getOldWorkOrderEntity().getCreatorId());
            Integer noApprovalRequired = beforeUpdateVO.getNoApprovalRequired();
            Integer updateLine = 0;
            if ( Objects.equals(noApprovalRequired, 1) ) {
                //TODO 剔除联系人
                JSONObject data = workOrderEntity.getData();
                JSONArray productArray = saasSaveHelp.formatSelectProduct4Save2(data, WorkOrderEnum.SPARE_PARTS.getAttr());
                FormDataUtil.removeSystemData(data);
                Object richTextData = removeRichText(data);
                workOrderEntity.setData(data);
                //产品保存
                Boolean productCanSee = formDataValidateProductHelp.attrCanSee(beforeUpdateVO.getExplainMap().get(WorkOrderEnum.SPARE_PARTS.getAttr()),workOrderEntity.getDataId(),workOrderEntity.getCreatorId(),formDataUpdateDTO.getLoginUser(),formDataUpdateDTO.getCorpid(),XbbRefTypeEnum.SUPPLIER.getCode());
                if (productCanSee){
                    workOrderService.saveProduct(productArray, corpid, workOrderEntity.getId(), formDataUpdateDTO.getFormId());
                    //获取工单剩余未出库产品信息及数量
                    List<WorkOrderProductEntity> workOrderProductList = workOrderProductService.getSurplusProduct(corpid, workOrderEntity.getId(), workOrderEntity, null);
                    int allOutbound;
                    if (workOrderProductList.isEmpty()) {
                        allOutbound = 1;
                    } else {
                        allOutbound = 0;
                    }
                    workOrderEntity.setAllOutbound(allOutbound);
                }
                updateLine = workOrderModel.update(workOrderEntity);
                JSONObject subForm = workOrderEntity.getSubFormData() == null ? new JSONObject(): workOrderEntity.getSubFormData();
                workOrderEntity.getData().putAll(subForm);
                workOrderEntity.getData().put(WorkOrderEnum.SPARE_PARTS.getAttr(), productArray);

                //文件柜数据保存
                saveFile(beforeUpdateVO.getExplainMap(), workOrderEntity, XbbRefTypeEnum.WORK_ORDER.getCode(), userVO);
                //富文本数据更新
                updateFormRichText(formDataUpdateDTO, richTextData);

            }
            updateVO = new UpdateVO(noApprovalRequired, workOrderEntity, updateLine, formDataUpdateDTO.getDataId(), userVO);
            return updateVO;
        } catch (XbbException e) {
            afterSaveRollBack(formDataUpdateDTO, updateVO, beforeUpdateVO, new ReRollBackEntity());
            throw e;
        } catch (Exception e) {
            afterSaveRollBack(formDataUpdateDTO, updateVO, beforeUpdateVO, new ReRollBackEntity());
            LOG.error("workOrderFormDataUpdateServiceImpl.update 出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }


    @Override
    public FormDataUpdateVO afterSave(FormDataUpdateDTO formDataUpdateDTO, BeforeUpdateVO beforeUpdateVO, UpdateVO updateVO, WorkOrderFormEntityExt workOrderFormEntity, WorkOrderEntity workOrderEntity, WorkOrderEntity oldWorkOrderEntity) throws XbbException {
        String corpid = formDataUpdateDTO.getCorpid();
        Long dataId = formDataUpdateDTO.getDataId();
        Integer businessType = formDataUpdateDTO.getBusinessType();
        try {
            FormDataUpdateVO formDataUpdateVO = new FormDataUpdateVO();
            Integer noApprovalRequired = updateVO.getNoApprovalRequired();
            if (Objects.equals(1, noApprovalRequired)) {


                SaasFormSaveDTO saasFormSaveDTO = new SaasFormSaveDTO();
                BeanUtil.copyProperties(formDataUpdateDTO, saasFormSaveDTO);
                saasFormSaveDTO.setBusinessType(XbbRefTypeEnum.WORK_ORDER.getCode());
                packageSaasFormUpdateSaveDTO(saasFormSaveDTO, workOrderEntity, oldWorkOrderEntity);
                saasFormSaveDTO.setIsNew(false);
                saasFormSaveDTO.setOldData(oldWorkOrderEntity.getData());
                saasFormSaveDTO.setNewData(workOrderEntity.getData());
                saasFormSaveDTO.setOldWorkOrderEntity(oldWorkOrderEntity);
                saasFormSaveDTO.setNewWorkOrderEntity(workOrderEntity);
                saasFormSaveDTO.setSaasNeedRedundantAttrPoJo(formDataUpdateDTO.getSaasNeedRedundantAttrPoJo());
                //保存工单后（负责团队保存）
                PaasFormDataEntity newPaasFormDataEntity = new PaasFormDataEntity();
                BeanUtil.copyProperties(workOrderEntity, newPaasFormDataEntity);
                teamDataHelp.saveUserTeam(saasFormSaveDTO.getSaasNeedRedundantAttrPoJo(), dataId, newPaasFormDataEntity, saasFormSaveDTO.getIsImport(), false);

                // 记录日志
                afterSaveLog(formDataUpdateDTO, workOrderFormEntity, workOrderEntity, oldWorkOrderEntity, updateVO, beforeUpdateVO);

                // api发起
                apiHook(formDataUpdateDTO, updateVO, beforeUpdateVO);
                // 业务规则
                activeRule(formDataUpdateDTO, beforeUpdateVO, updateVO);
                formDataUpdateVO.setMsg(I18nMessageUtil.getMessage(MessageConstant.FORM_ADD_RETURN_MSG));
                formDataUpdateVO.setCode(PaasConstant.FORM_ADD_RETURN_CODE);
            } else if (Objects.equals(noApprovalRequired, 2)) {
                // 自动拒绝
                formDataUpdateVO.setMsg(I18nMessageUtil.getMessage(MessageConstant.FORM_ADD_PROCESS_RETURN_MSG));
                formDataUpdateVO.setCode(PaasConstant.FORM_ADD_PROCESS_RETURN_CODE);
            } else {
                formDataUpdateVO.setMsg(I18nMessageUtil.getMessage(MessageConstant.FORM_ADD_PROCESS_RETURN_MSG));
                formDataUpdateVO.setCode(PaasConstant.FORM_ADD_PROCESS_RETURN_CODE);
                PaasProcessDataEntity paasProcessDataEntity = new PaasProcessDataEntity();
                paasProcessDataEntity.setCorpid(formDataUpdateDTO.getCorpid());
                paasProcessDataEntity.setFormDataId(dataId);
                paasProcessDataEntity.setBusinessType(businessType);
                paasProcessDataEntity.setSaasMark(formDataUpdateDTO.getSaasMark());
                proModelService.updateFormDataStatus(paasProcessDataEntity, FlowStatusEnum.IN_APPROVAL.getType());
            }
            formDataUpdateVO.setFormDataId(dataId);
            return formDataUpdateVO;
        } catch (XbbException e) {
            afterSaveRollBack(formDataUpdateDTO, updateVO, beforeUpdateVO, new ReRollBackEntity());
            throw e;
        } catch (Exception e) {
            afterSaveRollBack(formDataUpdateDTO, updateVO, beforeUpdateVO, new ReRollBackEntity());
            LOG.error("workOrderFormDataUpdateServiceImpl.afterSave 出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    @Override
    public void apiHook(FormDataUpdateDTO formDataUpdateDTO, UpdateVO updateVO, BeforeUpdateVO beforeUpdateVO) throws XbbException {
        // 第三方服务
        lowCodeExecuteService(formDataUpdateDTO, updateVO, beforeUpdateVO);
    }


    @Override
    public WorkOrderEntity getData(FormDataUpdateDTO formDataUpdateDTO,  WorkOrderEntity oldPaasFormDataEntity, JSONObject data, Long departmentId) throws XbbException {
        WorkOrderEntity workOrderEntity = new WorkOrderEntity();
        // 这行copy不能少，少了会出问题
        BeanUtil.copyProperties(oldPaasFormDataEntity, workOrderEntity);
        workOrderEntity.setId(formDataUpdateDTO.getDataId());
        workOrderEntity.setMenuId(formDataUpdateDTO.getMenuId());
        workOrderEntity.setFormId(formDataUpdateDTO.getFormId());
        // 所属部门的id，由前端传入
        workOrderEntity.setDepartmentId(departmentId);
        workOrderEntity.setSerialNo(formDataUpdateDTO.getSerialNo());
        workOrderEntity.setCorpid(formDataUpdateDTO.getCorpid());
        workOrderEntity.setData(data);
        return workOrderEntity;
    }

    @Override
    public WorkOrderEntity getImportData(FormDataUpdateDTO formDataUpdateDTO, Map<String, FieldAttrEntity> explainMap, WorkOrderEntity oldPaasFormDataEntity, JSONObject data, Long departmentId) throws XbbException {
        WorkOrderEntity workOrderEntity = getData(formDataUpdateDTO, oldPaasFormDataEntity, data, departmentId);
        // 覆盖导入 开启严控模式 ,流水号不更新
        FieldAttrEntity serialNoEntity = explainMap.get(FieldTypeEnum.SERIALNO.getAlias());
        if (Objects.nonNull(serialNoEntity) && Objects.equals(serialNoEntity.getStrictController(), BasicConstant.ONE)){
            workOrderEntity.setSerialNo(oldPaasFormDataEntity.getSerialNo());
        }
        return workOrderEntity;
    }

    @Override
    public BeforeUpdateVO startWorkFlowOrProcess(WorkOrderEntity workOrderEntity, WorkOrderEntity oldWorkOrderEntity, WorkOrderFormEntityExt workOrderFormEntityExt, SaasNeedRedundantAttrPojo saasNeedRedundantAttrPojo, FormDataUpdateDTO formDataUpdateDTO, Map<String, FieldAttrEntity> explainMap, List<FieldAttrEntity> explainList) throws XbbException {
        //是否启用新工作流
        if (isEnableNewWorkflow(formDataUpdateDTO, explainMap, workOrderEntity, oldWorkOrderEntity)) {
            if (!formDataUpdateDTO.getIsSatisfyTrigger()) {
                // 无需走工作流
                workOrderEntity.setFlowStatus(null);
            }
            BeforeUpdateVO beforeUpdateVO = new BeforeUpdateVO(explainMap, explainList, saasNeedRedundantAttrPojo, 1, workOrderEntity, oldWorkOrderEntity, workOrderFormEntityExt);
            Long backupDataId = backupData(formDataUpdateDTO, beforeUpdateVO, workOrderFormEntityExt, workOrderEntity, oldWorkOrderEntity);
            beforeUpdateVO.setBackupDataId(backupDataId);
            return beforeUpdateVO;
        }

        // 进入审批
        Integer noApprovalRequired = startProcess(formDataUpdateDTO, workOrderEntity, oldWorkOrderEntity, workOrderFormEntityExt, saasNeedRedundantAttrPojo);

        return new BeforeUpdateVO(explainMap, explainList, saasNeedRedundantAttrPojo, noApprovalRequired, workOrderEntity, oldWorkOrderEntity, workOrderFormEntityExt);
    }

    @Override
    public BeforeUpdateVO startWorkFlow(WorkOrderEntity workOrderEntity, WorkOrderEntity oldWorkOrderEntity, WorkOrderFormEntityExt workOrderFormEntityExt, SaasNeedRedundantAttrPojo saasNeedRedundantAttrPojo, FormDataUpdateDTO formDataUpdateDTO, Map<String, FieldAttrEntity> explainMap, List<FieldAttrEntity> explainList) throws XbbException {
        BeforeUpdateVO beforeUpdateVO = new BeforeUpdateVO(explainMap, explainList, saasNeedRedundantAttrPojo, 1, workOrderEntity, oldWorkOrderEntity, workOrderFormEntityExt);
        if (isEnableNewWorkflow(formDataUpdateDTO, explainMap, workOrderEntity, oldWorkOrderEntity)) {
            if (!formDataUpdateDTO.getIsSatisfyTrigger()) {
                // 无需走工作流
                workOrderEntity.setFlowStatus(null);
            }
            Long backupDataId = backupData(formDataUpdateDTO, beforeUpdateVO, workOrderFormEntityExt, workOrderEntity, oldWorkOrderEntity);
            beforeUpdateVO.setBackupDataId(backupDataId);
        }
        return beforeUpdateVO;
    }

    @Override
    public Integer startProcess(FormDataUpdateDTO formDataUpdateDTO, WorkOrderEntity paasFormDataEntity, WorkOrderEntity oldPaasFormDataEntity, WorkOrderFormEntityExt workOrderFormEntityExt, SaasNeedRedundantAttrPojo saasNeedRedundantAttrPojo) throws XbbException {
        Integer noApprovalRequired = 1;
        if (workOrderFormEntityExt.getIsProcessForm().equals(1)) {
            StartProcessDTO startProcessDTO = new StartProcessDTO();
            BeanUtil.copyProperties(formDataUpdateDTO, startProcessDTO);
            startProcessDTO.setData(formDataUpdateDTO.getDataList());
            startProcessDTO.setFormDataId(formDataUpdateDTO.getDataId());
            startProcessDTO.setCreatorId(formDataUpdateDTO.getUserId());
            startProcessDTO.setSaasNeedRedundantAttrPoJo(saasNeedRedundantAttrPojo);

            StartProcessVO startProcessVO = processStartHelp.startProcess(startProcessDTO, oldPaasFormDataEntity);
            if (Objects.isNull(startProcessVO)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.START_PROCESS_ERROR);
            }
            noApprovalRequired = startProcessVO.getNoApprovalRequired();
        }
        return noApprovalRequired;
    }

//    @Override
    public void afterSaveRollBack( FormDataUpdateDTO formDataUpdateDTO, UpdateVO updateVO, BeforeUpdateVO beforeUpdateVO,  ReRollBackEntity reRollBackEntity) throws XbbException {
        try {
            WorkOrderEntity workOrderEntity = null;
            if (Objects.nonNull(updateVO)) {
                workOrderEntity = updateVO.getWorkOrderEntity();
            }
            WorkOrderEntity oldWorkOrderEntity = beforeUpdateVO.getOldWorkOrderEntity();
            Long dataId = formDataUpdateDTO.getDataId();
            String corpid = formDataUpdateDTO.getCorpid();
            Integer saasMark = formDataUpdateDTO.getSaasMark();
            Integer businessType = formDataUpdateDTO.getBusinessType();
            oldWorkOrderEntity.getData().remove(FieldTypeEnum.UPDATETIME.getAlias());
            oldWorkOrderEntity.getData().remove(FieldTypeEnum.ADDTIME.getAlias());
            oldWorkOrderEntity.getData().remove(FieldTypeEnum.OWNERID.getAlias());
            oldWorkOrderEntity.getData().remove(FieldTypeEnum.CREATORID.getAlias());
            oldWorkOrderEntity.getData().remove(FieldTypeEnum.SERIALNO.getAlias());
            proEsHelper.reductionEsInUpdate(oldWorkOrderEntity,oldWorkOrderEntity.getId(),oldWorkOrderEntity.getCorpid(), businessType,saasMark);

            AbstractFormDataUpdateRollBackService rollBackService = FormDataUpdateRollBackFactory.getRollBackService(businessType, saasMark);
            if (Objects.nonNull(rollBackService)) {
                rollBackService.rollBack4Update(workOrderEntity, oldWorkOrderEntity, dataId, corpid, saasMark, businessType, reRollBackEntity);
            }
        } catch (Exception e) {
            LOG.error("workOrderDataFormDataUpdateServiceImpl.afterSaveRollBack回滚失败：", e);
        }

    }
    /**
     * 执行业务规则
     * @param formDataUpdateDTO
     * @param beforeUpdateVO
     * @param updateVO
     * @throws XbbException
     */
    @Override
    public void activeRule(FormDataUpdateDTO formDataUpdateDTO, BeforeUpdateVO beforeUpdateVO, UpdateVO updateVO) throws XbbException{
        WorkOrderFormEntity paasFormEntityExt = beforeUpdateVO.getWorkOrderFormEntity();
        String businessRules = paasFormEntityExt.getBusinessRules();
        if (Objects.equals("1", businessRules) && Objects.equals(1, updateVO.getUpdateLine())) {
            WorkOrderEntity workOrderEntity = beforeUpdateVO.getWorkOrderEntity();
            WorkOrderEntity oldWorkOrderEntity = beforeUpdateVO.getOldWorkOrderEntity();
            IndexTypeEnum indexTypeEnum = IndexTypeEnum.IDX_SAAS_WORK_ORDER_SUB;
            paasFormSubDataModel.transferSubForm(oldWorkOrderEntity, indexTypeEnum);
            PaasFormDataEntity newFormData = new PaasFormDataEntity();
            BeanUtil.copyProperties(workOrderEntity, newFormData);
            PaasFormDataEntity oldPaasFormDataEntity = new PaasFormDataEntity();
            BeanUtil.copyProperties(oldWorkOrderEntity, oldPaasFormDataEntity);
            ActiveRuleDTO activeRuleDTO = new ActiveRuleDTO(new ArrayList<>(), newFormData,  oldPaasFormDataEntity, beforeUpdateVO.getExplainList(), formDataUpdateDTO.getDataId(),
                    formDataUpdateDTO.getBusinessType(), formDataUpdateDTO.getSaasMark(), formDataUpdateDTO.getCorpid(),formDataUpdateDTO.getLoginUser(), 1, formDataUpdateDTO.getPlatform(),
                    formDataUpdateDTO.getHttpHeader(), formDataUpdateDTO.getBrowserInfo(), formDataUpdateDTO.getIp(), formDataUpdateDTO.getLocale(), formDataUpdateDTO.getIsImport());
            formDataActiveRuleHelp.activeRule(activeRuleDTO);
        }
    }
    /**
     * 低代码执行服务
     * @param formDataUpdateDTO
     * @param beforeUpdateVO
     * @param updateVO
     * @throws XbbException
     */
    @Override
    public void lowCodeExecuteService(FormDataUpdateDTO formDataUpdateDTO, UpdateVO updateVO, BeforeUpdateVO beforeUpdateVO) throws XbbException {
        try {
            PaasFormDataEntity paasFormDataEntity = new PaasFormDataEntity();
            BeanUtil.copyProperties(updateVO.getWorkOrderEntity(), paasFormDataEntity);
            updateVO.setPaasFormDataEntity(paasFormDataEntity);
            lowCodeExecuteHelp.lowCodeExecuteService(formDataUpdateDTO, updateVO, beforeUpdateVO);
        } catch (Exception e) {
            LOG.error("com.xbongbong.paas.service.impl.workOrderDataFormDataUpdateServiceImpl.lowCodeExecuteService fail", e);
        }

    }

    @Override
    public UpdateVO updateForWorkflow(FormDataUpdateDTO formDataUpdateDTO, BeforeUpdateVO beforeUpdateVO, WorkOrderFormEntityExt workOrderFormEntity, WorkOrderEntity workOrderEntity, WorkOrderEntity oldWorkOrderEntity) throws XbbException {
        UpdateVO updateVO = new UpdateVO();
        try {
            String corpid = formDataUpdateDTO.getCorpid();
            UserVO userVO = userHelp.getUserName(formDataUpdateDTO.getCorpid(), formDataUpdateDTO.getUserId(), formDataUpdateDTO.getLoginUserName(), beforeUpdateVO.getOldWorkOrderEntity().getFlowStatus(), beforeUpdateVO.getOldWorkOrderEntity().getCreatorId());
            Integer noApprovalRequired = beforeUpdateVO.getNoApprovalRequired();
            Integer updateLine = 0;
            //TODO 剔除联系人
            JSONObject data = workOrderEntity.getData();
            JSONArray productArray = saasSaveHelp.formatSelectProduct4Save2(data, WorkOrderEnum.SPARE_PARTS.getAttr());
            FormDataUtil.removeSystemData(data);
            Object richTextData = removeRichText(data);
            workOrderEntity.setData(data);
            //产品保存
            Boolean productCanSee = formDataValidateProductHelp.attrCanSee(beforeUpdateVO.getExplainMap().get(WorkOrderEnum.SPARE_PARTS.getAttr()),workOrderEntity.getDataId(),workOrderEntity.getCreatorId(),formDataUpdateDTO.getLoginUser(),formDataUpdateDTO.getCorpid(),XbbRefTypeEnum.SUPPLIER.getCode());
            if (productCanSee){
                workOrderService.saveProduct(productArray, corpid, workOrderEntity.getId(), formDataUpdateDTO.getFormId());
                //获取工单剩余未出库产品信息及数量
                List<WorkOrderProductEntity> workOrderProductList = workOrderProductService.getSurplusProduct(corpid, workOrderEntity.getId(), workOrderEntity, null);
                int allOutbound;
                if (workOrderProductList.isEmpty()) {
                    allOutbound = 1;
                } else {
                    allOutbound = 0;
                }
                workOrderEntity.setAllOutbound(allOutbound);
            }
            updateLine = workOrderModel.update(workOrderEntity);
            JSONObject subForm = workOrderEntity.getSubFormData() == null ? new JSONObject(): workOrderEntity.getSubFormData();
            workOrderEntity.getData().putAll(subForm);
            workOrderEntity.getData().put(WorkOrderEnum.SPARE_PARTS.getAttr(), productArray);

            //文件柜数据保存
//            cabinetFileService.saveDataCabinetFile(beforeUpdateVO.getExplainMap(), workOrderEntity.getData(), workOrderEntity.getSubFormData(), formDataUpdateDTO.getCorpid(),formDataUpdateDTO.getDataId(), XbbRefTypeEnum.WORK_ORDER.getCode(), userVO.getUserId());

            //富文本数据保存
            Integer updateRichTextLine = updateFormRichText(formDataUpdateDTO, richTextData);
            //表单数据和富文本数据其中有一个编辑就要进工作流
            updateLine = Objects.equals(updateLine, 1) || Objects.equals(updateRichTextLine, 1) ? 1 : 0;
            updateVO = new UpdateVO(noApprovalRequired, workOrderEntity, updateLine, formDataUpdateDTO.getDataId(), userVO);
            return updateVO;
        } catch (XbbException e) {
            afterSaveRollBack(formDataUpdateDTO, updateVO, beforeUpdateVO, new ReRollBackEntity());
            throw e;
        } catch (Exception e) {
            afterSaveRollBack(formDataUpdateDTO, updateVO, beforeUpdateVO, new ReRollBackEntity());
            LOG.error("workOrderFormDataUpdateServiceImpl.update 出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    @Override
    public FormDataUpdateVO afterSaveForWorkflow(FormDataUpdateDTO formDataUpdateDTO, BeforeUpdateVO beforeUpdateVO, UpdateVO updateVO, WorkOrderFormEntityExt workOrderFormEntity, WorkOrderEntity workOrderEntity, WorkOrderEntity oldWorkOrderEntity) throws XbbException {
        String corpid = formDataUpdateDTO.getCorpid();
        Long dataId = formDataUpdateDTO.getDataId();
        Integer businessType = formDataUpdateDTO.getBusinessType();
        try {
            FormDataUpdateVO formDataUpdateVO = new FormDataUpdateVO();
            Integer noApprovalRequired = updateVO.getNoApprovalRequired();


            SaasFormSaveDTO saasFormSaveDTO = new SaasFormSaveDTO();
            BeanUtil.copyProperties(formDataUpdateDTO, saasFormSaveDTO);
            saasFormSaveDTO.setBusinessType(XbbRefTypeEnum.WORK_ORDER.getCode());
            packageSaasFormUpdateSaveDTO(saasFormSaveDTO, workOrderEntity, oldWorkOrderEntity);
            saasFormSaveDTO.setIsNew(false);
            saasFormSaveDTO.setOldData(oldWorkOrderEntity.getData());
            saasFormSaveDTO.setNewData(workOrderEntity.getData());
            saasFormSaveDTO.setOldWorkOrderEntity(oldWorkOrderEntity);
            saasFormSaveDTO.setNewWorkOrderEntity(workOrderEntity);
            saasFormSaveDTO.setSaasNeedRedundantAttrPoJo(formDataUpdateDTO.getSaasNeedRedundantAttrPoJo());
            //保存工单后（负责团队保存）
            PaasFormDataEntity newPaasFormDataEntity = new PaasFormDataEntity();
            BeanUtil.copyProperties(workOrderEntity, newPaasFormDataEntity);
            saasFormSaveDTO.getSaasNeedRedundantAttrPoJo().getTeamAfterVerifyDTO().getAddMainUserMap().clear();
            teamDataHelp.saveUserTeam(saasFormSaveDTO.getSaasNeedRedundantAttrPoJo(), dataId, newPaasFormDataEntity, saasFormSaveDTO.getIsImport(), true);

            // 记录日志
//            afterSaveLog(formDataUpdateDTO, null, updateVO, beforeUpdateVO);
            // api发起
//            apiHook(formDataUpdateDTO, updateVO, beforeUpdateVO);
            // 业务规则
//            activeRule(formDataUpdateDTO, beforeUpdateVO, updateVO);

            formDataUpdateVO.setMsg(I18nMessageUtil.getMessage(MessageConstant.FORM_ADD_RETURN_MSG));
            formDataUpdateVO.setCode(PaasConstant.FORM_ADD_RETURN_CODE);
//            PaasProcessDataEntity paasProcessDataEntity = new PaasProcessDataEntity();
//            paasProcessDataEntity.setCorpid(formDataUpdateDTO.getCorpid());
//            paasProcessDataEntity.setFormDataId(dataId);
//            paasProcessDataEntity.setBusinessType(businessType);
//            paasProcessDataEntity.setSaasMark(formDataUpdateDTO.getSaasMark());
//            proModelService.updateFormDataStatus(paasProcessDataEntity, FlowStatusEnum.IN_APPROVAL.getType());
            formDataUpdateVO.setFormDataId(dataId);
            return formDataUpdateVO;
        } catch (XbbException e) {
            afterSaveRollBack(formDataUpdateDTO, updateVO, beforeUpdateVO, new ReRollBackEntity());
            throw e;
        } catch (Exception e) {
            afterSaveRollBack(formDataUpdateDTO, updateVO, beforeUpdateVO, new ReRollBackEntity());
            LOG.error("workOrderFormDataUpdateServiceImpl.afterSave 出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    @Override
    public Long backupData(FormDataUpdateDTO formDataUpdateDTO, BeforeUpdateVO beforeUpdateVO, WorkOrderFormEntityExt workOrderFormEntity, WorkOrderEntity workOrderEntity, WorkOrderEntity oldWorkOrderEntity) {
        String corpid = formDataUpdateDTO.getCorpid();
        Integer isProcessForm = workOrderFormEntity.getIsProcessForm();
        if (!formDataUpdateDTO.getIsSatisfyTrigger()) {
            return null;
        }
        JSONObject data = oldWorkOrderEntity.getData();
        FormDataUtil.setSystemData(data, oldWorkOrderEntity);

        data = backupDataOtherInfo(data, corpid, oldWorkOrderEntity.getId());

        long now = DateTimeUtil.getInt();
        WorkflowBackupDataEntity workflowBackupDataEntity = new WorkflowBackupDataEntity(corpid, oldWorkOrderEntity.getAppId(), oldWorkOrderEntity.getFormId(), oldWorkOrderEntity.getMenuId(), 0L, 0L, oldWorkOrderEntity.getId(), data, now, now, DelEnum.NORMAL.getDel());
        workflowBackupDataModel.insert(workflowBackupDataEntity);
        //富文本数据备份
        backupRichText(workflowBackupDataEntity, formDataUpdateDTO.getBusinessType(), formDataUpdateDTO.getSaasMark());
        return workflowBackupDataEntity.getId();

    }

    @Override
    public JSONObject backupDataOtherInfo(JSONObject data, String corpid, Long dataId) {
        List<WorkOrderProductEntity> workOrderProductEntities = workOrderProductModel.getProductsByWorkOrderId(dataId, corpid);
        data.put(StringConstant.PRODUCT, workOrderProductEntities);

        List<WorkOrderFlowUserEntity> userEntityList = workOrderFlowUserModel.getUserListByWorkorderId(corpid, dataId);
        data.put(StringConstant.USER_TEAM, userEntityList);
        return data;
    }
}
